with ($ns("g"))
{
    g.ReaderClass = function()
    {
        var me = new EventDispatcher();

        me.init = function()
        {
            
        };
        
        me.getSubscriptions = function(p_options)
        {   
            var dataType = "json";
            if (p_options.dataType != null)
            {
                dataType = p_options.dataType;
            }
            
            g.ReaderService.get({
                path: "/subscription/list?output=json",
                dataType: dataType,
                success: p_options.success,
                error: p_options.err
            });
        };
        
        
        
        
        me.getFeeds = function(p_options)
        {
            console.log("Getting feeds...");
            
            var options = {
                path: "user/-/state/com.google/reading-list",
                dataType: "json",
                count: 20
            };
            $.extend(options, p_options);
            
            var data = {
                n: options.count
            };
            
            if (options.unreadOnly)
            {
                data.xt = "user/-/state/com.google/read";
            }
            
            if (options.path.startsWith("feed/http"))
            {
                options.path = options.path.substr(0, 5) + escape(options.path.substr(5));
            }
            
            
            
            var cached = false;
            var cacheTime = fp.Storage.get("cache.feedCache.time");
            if (cacheTime)
            {
                cached = true;
                if (!navigator.onLine)
                {
                    cached = true;
                    console.log("Force to use cache: chrome is offline now. ");
                }
                else if (!fp.caches.FeedCache.isEnabled())
                {
                    cached = false;
                    console.log("Can't use FeedCache: FeedCache is disabled.");
                }
                else if (options.noCache)
                {
                    cached = false;
                    console.log("Can't use FeedCache: 'noCache' option is on.");
                }
                else if (options.unreadOnly)
                {
                    cached = false;
                    console.log("Can't use FeedCache: 'unreadOnly' option is on.");
                }
                else if (options.path != "user/-/state/com.google/reading-list")
                {
                    cached = false;
                    console.log("Can't use FeedCache: path is not reading-list");
                }
                else if (options.continuation != null)
                {
                    cached = false;
                    console.log("Can't use FeedCache: continuation is not empty");
                }
                else 
                {
                    var timeout = fp.Preferences.get("cache.feedCache.interval", 2) + 1;
                    if (new Date() - cacheTime > timeout * 60000)
                    {
                        cached = false;
                        console.log("Can't use FeedCache: cached data is expired (" + timeout + " minute(s)).");
                    }
                }
            }
            else
            {
                console.log("Can't use cache, there's no cached data in the local storage.");
            }
            
            
            if (cached)
            {
                if (options.success)
                {
                    var result = $.parseJSON(fp.Storage.get("cache.feedCache"));
                    result.cached = true;
                    if (!navigator.onLine)
                    {
                        result.continuation = null;
                    }
                    console.log("Getting feeds - Use cached data!!!");
                    options.success(result);
                    return;
                }
            }
            else
            {
                if (options.continuation != null)
                {
                    data.c = options.continuation;
                }
                console.log("Sending request - " + JSON.stringify(options));
                g.ReaderService.get({
                    path: "/stream/contents/" + options.path,
                    data: data,
                    dataType: options.dataType,
                    success: options.success,
                    error: options.err
                });
            }
        };
        
        
        
        
        
        
        me.addTag = function(p_feed, p_tag)
        {
            if (g.Account.token != null)
            {
                var data = {
                    a: p_tag,
                    i: p_feed.id,
                    async: "true",
                    s: p_feed.origin.streamId,
                    T: g.Account.token
                };
                g.ReaderService.post({
                    path: "/edit-tag",
                    data: data,
                    error: _onerror
                });
            }
        };
        
        me.removeTag = function(p_feed, p_tag)
        {
            if (g.Account.token != null)
            {
                var data = {
                    r: p_tag,
                    i: p_feed.id,
                    async: "true",
                    s: p_feed.origin.streamId,
                    T: g.Account.token
                };
                g.ReaderService.post({
                    path: "/edit-tag",
                    data: data,
                    error: _onerror
                });
            }
        };
        
        
        
        
        me.addState = function(p_feed, p_state)
        {
            me.addTag(p_feed, "user/-/state/com.google/" + p_state);
        };
        
        me.removeState = function(p_feed, p_state)
        {
            me.removeTag(p_feed, "user/-/state/com.google/" + p_state);
        };
        
        
        
        
        me.addStar = function(p_feed)
        {
            me.addState(p_feed, "starred")
        };
        
        me.removeStar = function(p_feed)
        {
            me.removeState(p_feed, "starred");
        };
        
        
        
        
        me.markAsRead = function(p_feed)
        {
            me.addState(p_feed, "read");
        };
        
        
        
        
        
        
        
        function _onerror(p_request, p_status, p_error)
        {
            var message = null;
            switch (p_request.status)
            {
                case 0:
                case 400:
                case 403:
                case 500:
                case 504:
                    message = $msg("fp", "ERR_HTTP_" + p_request.status);
                    break;
                default:
                    message = $msg("fp", "ERR_HTTP_COMMON");
            }
            mx.warn(message);
        }
        
        
        return me;
    };
    
    g.Reader = new g.ReaderClass();
    g.Reader.init();
}